﻿using JESAI.HttpRequestMonitor.Core.Abstracts;
using JESAI.HttpRequestMonitor.Dashboard.Models;
using JESAI.HttpRequestMonitor.Dashboard.Services.Language;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace JESAI.HttpRequestMonitor.Dashboard.Services.Quartz
{
    public class ScheduleService
    {
        private const string SchedulerGroup = "HttpRequestMonitor_Scheduler";

        private const string SchedulerTag = "monitor_";

        public IScheduler scheduler;

        private IRequestMonitorStorage _storage;

        private DashboardOptions _options;


        public ScheduleService(IRequestMonitorStorage storage, IOptions<DashboardOptions> options, LanguageService languageService)
        {
            _storage = storage;

            _options = options.Value;

            scheduler = scheduler ?? new StdSchedulerFactory().GetScheduler().Result;
        }

        public async Task InitAsync()
        {
            await ClearDataJobAsync();

            await InitMonitorScheduleJobModelAsync();

            await scheduler.Start();
        }


        public async Task InitMonitorScheduleJobModelAsync()
        {
            List<IMonitorScheduleJobModel> list = await _storage.GetMonitorScheduleJobs();

            if (list == null || list.Count == 0)
            {
                return;
            }

            list = list.Where(x => x.Status == 1).ToList();

            foreach (var item in list)
            {
                await ScheduleJobAsync(item);
            }

        }

        private async Task ScheduleJobAsync(IMonitorScheduleJobModel model)
        {
            var job = JobBuilder.Create<MonitorBackendJob>().
                   WithIdentity(SchedulerTag + model.Id, SchedulerGroup)
                   .SetJobData(new JobDataMap { { "job", model } }).Build();

            var trigger = TriggerBuilder.Create().WithCronSchedule(model.CronLike).Build();

            await scheduler.ScheduleJob(job, trigger);

        }

        private async Task DeleteJobAsync(IJobDetail job)
        {
            if (scheduler.CheckExists(job.Key).Result)
            {
                await scheduler.PauseJob(job.Key);

                await scheduler.DeleteJob(job.Key);
            }
        }

        public async Task UpdateMonitorScheduleJobModelAsync()
        {
            List<IMonitorScheduleJobModel> list = await _storage.GetMonitorScheduleJobs();

            if (list == null || list.Count == 0)
            {
                return;
            }

            foreach (var k in list)
            {
                var job = await scheduler.GetJobDetail(new JobKey(SchedulerTag + k.Id, SchedulerGroup));

                if (job == null)
                {
                    if (k.Status == 1) await ScheduleJobAsync(k);
                }
                else
                {
                    if (k.Status == 0)
                    {
                        await DeleteJobAsync(job);
                    }
                    else
                    {
                        IMonitorScheduleJobModel MonitorScheduleJobModel = job.JobDataMap.Get("job") as IMonitorScheduleJobModel;

                        // 判断是否有修改，如果修改后，重置Job
                        if (JsonConvert.SerializeObject(k) != JsonConvert.SerializeObject(MonitorScheduleJobModel))
                        {
                            await DeleteJobAsync(job);
                            await ScheduleJobAsync(k);
                        }
                    }
                }
            }
        }

        public async Task ClearDataJobAsync()
        {
            var job = JobBuilder.Create<ClearReportsDataJob>().Build();

            var trigger = TriggerBuilder.Create().WithCronSchedule(SysConst.ClearDataCornLike).Build();

            await scheduler.ScheduleJob(job, trigger);
        }

    }
}
